package org.smr.ministore.entities;

import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import org.apache.commons.collections.CollectionUtils;
import org.blade.entities.base.BizEntity;
import org.smr.ministore.entities.validator.OperationValidator;
import org.smr.ministore.entities.validator.concre.ReferenceValidator;
import org.smr.ministore.entities.vo.Assign2OrganVO;
import org.smr.ministore.entities.vo.Assign2OrgansVO;
import org.smr.ministore.entities.vo.GoodsVO;
import org.smr.ministore.entities.vo.OrganVO;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Goods实体,对应表：t_goods
 **/
public class Goods extends Assign2Organ<GoodsOrgan> {

    /**
     * 机构路径
     **/
    private java.lang.String organPath;

    /**
     * 设置机构路径的值
     *
     * @param organPath
     **/
    public void setOrganPath(java.lang.String organPath) {
        this.organPath = organPath;
    }

    /**
     * 获取机构路径的值
     **/
    public java.lang.String getOrganPath() {
        return this.organPath;
    }


    /**
     * 组织机构名称
     **/
    private java.lang.String organName;

    /**
     * 设置组织机构名称的值
     *
     * @param organName
     **/
    public void setOrganName(java.lang.String organName) {
        this.organName = organName;
    }

    /**
     * 获取组织机构名称的值
     **/
    public java.lang.String getOrganName() {
        return this.organName;
    }


    /**
     * 商品分类
     **/
    @JSONField(
            serializeUsing = ToStringSerializer.class
    )
    private java.lang.Long typeId;

    /**
     * 设置商品分类的值
     *
     * @param typeId
     **/
    public void setTypeId(java.lang.Long typeId) {
        this.typeId = typeId;
    }

    /**
     * 获取商品分类的值
     **/
    public java.lang.Long getTypeId() {
        return this.typeId;
    }


    /**
     * 类型路径
     **/
    private java.lang.String typePath;

    /**
     * 设置类型路径的值
     *
     * @param typePath
     **/
    public void setTypePath(java.lang.String typePath) {
        this.typePath = typePath;
    }

    /**
     * 获取类型路径的值
     **/
    public java.lang.String getTypePath() {
        return this.typePath;
    }


    /**
     * 商品名称
     **/
    private java.lang.String goodsName;

    /**
     * 设置商品名称的值
     *
     * @param goodsName
     **/
    public void setGoodsName(java.lang.String goodsName) {
        this.goodsName = goodsName;
    }

    /**
     * 获取商品名称的值
     **/
    public java.lang.String getGoodsName() {
        return this.goodsName;
    }


    /**
     * 供应商
     **/
    @JSONField(
            serializeUsing = ToStringSerializer.class
    )
    private java.lang.Long supplierId;

    /**
     * 设置供应商的值
     *
     * @param supplierId
     **/
    public void setSupplierId(java.lang.Long supplierId) {
        this.supplierId = supplierId;
    }

    /**
     * 获取供应商的值
     **/
    public java.lang.Long getSupplierId() {
        return this.supplierId;
    }


    /**
     * 商品图片url
     **/
    private java.lang.String goodsImg;

    /**
     * 设置商品图片url的值
     *
     * @param goodsImg
     **/
    public void setGoodsImg(java.lang.String goodsImg) {
        this.goodsImg = goodsImg;
    }

    /**
     * 获取商品图片url的值
     **/
    public java.lang.String getGoodsImg() {
        return this.goodsImg;
    }


    /**
     * 商品描述
     **/
    private java.lang.String goodsDescribe;

    /**
     * 设置商品描述的值
     *
     * @param goodsDescribe
     **/
    public void setGoodsDescribe(java.lang.String goodsDescribe) {
        this.goodsDescribe = goodsDescribe;
    }

    /**
     * 获取商品描述的值
     **/
    public java.lang.String getGoodsDescribe() {
        return this.goodsDescribe;
    }


    /**
     * 商品规格单位
     **/
    private java.lang.String unit;

    /**
     * 设置商品规格单位的值
     *
     * @param unit
     **/
    public void setUnit(java.lang.String unit) {
        this.unit = unit;
    }

    /**
     * 获取商品规格单位的值
     **/
    public java.lang.String getUnit() {
        return this.unit;
    }


    /**
     * 商品规格值
     **/
    private java.lang.Integer unitValue;

    /**
     * 设置商品规格值的值
     *
     * @param unitValue
     **/
    public void setUnitValue(java.lang.Integer unitValue) {
        this.unitValue = unitValue;
    }

    /**
     * 获取商品规格值的值
     **/
    public java.lang.Integer getUnitValue() {
        return this.unitValue;
    }


    /**
     * 商品产地
     **/
    private java.lang.String productionPlace;

    /**
     * 设置商品产地的值
     *
     * @param productionPlace
     **/
    public void setProductionPlace(java.lang.String productionPlace) {
        this.productionPlace = productionPlace;
    }

    /**
     * 获取商品产地的值
     **/
    public java.lang.String getProductionPlace() {
        return this.productionPlace;
    }


    /**
     * 所属系统
     **/
    private java.lang.Integer sys;

    /**
     * 设置所属系统的值
     *
     * @param sys
     **/
    public void setSys(java.lang.Integer sys) {
        this.sys = sys;
    }

    /**
     * 获取所属系统的值
     **/
    public java.lang.Integer getSys() {
        return this.sys;
    }


    /**
     * 是否删除（1删除，0未删除）
     **/
    private boolean isDeleted;




    /**
     * 是否可被引用（1：是，0：否）
     **/
    private java.lang.Integer quote;

    /**
     * 设置是否可被引用（1：是，0：否）的值
     *
     * @param quote
     **/
    public void setQuote(java.lang.Integer quote) {
        this.quote = quote;
    }

    /**
     * 获取是否可被引用（1：是，0：否）的值
     **/
    public java.lang.Integer getQuote() {
        return this.quote;
    }


    /**
     * 创建者
     **/
    private java.lang.Long createBy;

    /**
     * 设置创建者的值
     *
     * @param createBy
     **/
    public void setCreateBy(java.lang.Long createBy) {
        this.createBy = createBy;
    }

    /**
     * 获取创建者的值
     **/
    public java.lang.Long getCreateBy() {
        return this.createBy;
    }


    /**
     * 修改者
     **/
    private java.lang.Long updateBy;

    /**
     * 设置修改者的值
     *
     * @param updateBy
     **/
    public void setUpdateBy(java.lang.Long updateBy) {
        this.updateBy = updateBy;
    }

    /**
     * 获取修改者的值
     **/
    public java.lang.Long getUpdateBy() {
        return this.updateBy;
    }


    /**
     *
     **/
    private java.lang.String remark;

    /**
     * 设置的值
     *
     * @param remark
     **/
    public void setRemark(java.lang.String remark) {
        this.remark = remark;
    }

    /**
     * 获取的值
     **/
    public java.lang.String getRemark() {
        return this.remark;
    }


    /**
     * 创建时间 查询时间开始
     **/
    private java.util.Date createDateStart;

    /**
     * 创建时间 查询时间结束
     **/
    private java.util.Date createDateEnd;


    /**
     * 设置创建时间Start的值
     *
     * @param createDateStart
     **/
    public void setCreateDateStart(java.util.Date createDateStart) {
        this.createDateStart = createDateStart;
    }

    /**
     * 获取创建时间Start的值
     **/
    public java.util.Date getCreateDateStart() {
        return this.createDateStart;
    }

    /**
     * 设置创建时间End的值
     *
     * @param createDateEnd
     **/
    public void setCreateDateEnd(java.util.Date createDateEnd) {
        this.createDateEnd = createDateStart;
    }

    /**
     * 获取创建时间End的值
     **/
    public java.util.Date getCreateDateEnd() {
        return this.createDateEnd;
    }


    /**
     * 更新时间 查询时间开始
     **/
    private java.util.Date updateDateStart;

    /**
     * 更新时间 查询时间结束
     **/
    private java.util.Date updateDateEnd;


    /**
     * 设置更新时间Start的值
     *
     * @param updateDateStart
     **/
    public void setUpdateDateStart(java.util.Date updateDateStart) {
        this.updateDateStart = updateDateStart;
    }

    /**
     * 获取更新时间Start的值
     **/
    public java.util.Date getUpdateDateStart() {
        return this.updateDateStart;
    }

    /**
     * 设置更新时间End的值
     *
     * @param updateDateEnd
     **/
    public void setUpdateDateEnd(java.util.Date updateDateEnd) {
        this.updateDateEnd = updateDateStart;
    }

    /**
     * 获取更新时间End的值
     **/
    public java.util.Date getUpdateDateEnd() {
        return this.updateDateEnd;
    }


    private OrganVO assignee;

    public OrganVO getAssignee() {
        return assignee;
    }

    public void setAssigneeId(Long assigneeId) {
        if (Objects.isNull(assignee)) {
            this.assignee = OrganVO.init(assigneeId, null, null);
            return;
        }
        this.getAssignee().setId(assigneeId);
    }

    public void setAssignee(OrganVO assignee) {
        this.assignee = assignee;
    }

    public boolean getIsDeleted() {
        return isDeleted;
    }

    public void setIsDeleted(boolean deleted) {
        isDeleted = deleted;
    }

    /**
     * 商品指派
     *
     * @return GoodsOrgan 组织商品
     */
    public GoodsOrgan assignTo(OrganVO assignee) {
        GoodsOrgan goodsOrgan = new GoodsOrgan();
        goodsOrgan.setGoodsId(this.getId());
        goodsOrgan.setOrganId(assignee.getId());
        goodsOrgan.setOrganPath(assignee.getOrganPath());
        goodsOrgan.setCreateBy(super.getCreateBy());
        goodsOrgan.setUpdateBy(super.getUpdateBy());
        return goodsOrgan;
    }

    @Override
    public void attachValue(GoodsOrgan organ) {
        organ.setGoodsId(this.getId());
    }

    @Override
    public GoodsOrgan initReference() {
        return new GoodsOrgan();
    }

    /**
     * 商品指派
     */
    private GoodsOrgan assign() {
        return this.assignTo(assignee);
    }


    /**
     * 商品指派批量组织
     *
     * @param assigneeOrgans
     * @return List<GoodsOrgan>
     */
    public List<GoodsOrgan> assignTo(Assign2OrgansVO assigneeOrgans) {
        this.setId(assigneeOrgans.getId());
        List<OrganVO> assignees = assigneeOrgans.getAssignees();
        List<GoodsOrgan> goodsOrgans = assignees.stream().map(this::assignTo).collect(Collectors.toList());
        return goodsOrgans;
    }

    /**
     * 批量商品指派给组织
     *
     * @param assign2Organ Assign2OrganVO 商品集合
     * @return List<GoodsOrgan>
     */
    public List<GoodsOrgan> assignTo(Assign2OrganVO assign2Organ) {
        List<GoodsVO> goodsList = assign2Organ.getGoodsList();
        List<GoodsOrgan> goodsOrgans = new ArrayList<>();
        goodsList.forEach(goodsVO -> {
            GoodsOrgan goodsOrgan = new GoodsOrgan();
            goodsOrgan.setGoodsId(goodsVO.getId());
            goodsOrgan.setUpdateBy(assign2Organ.getUpdateBy());
            goodsOrgan.setCreateBy(assign2Organ.getCreateBy());
            goodsOrgan.setOrganId(assign2Organ.getId());
            goodsOrgans.add(goodsOrgan);
        });
        return goodsOrgans;
    }

    /**
     * 根据持久化的关联得出需要指派的组织
     *
     * @param goodsOrgansPersistence 持久化的关联
     * @param assignee               被指派的组织
     * @return Assign2OrgansVO
     */
    public Assign2OrgansVO want2Assign(List<GoodsOrgan> goodsOrgansPersistence, Assign2OrgansVO assignee) {
        if (CollectionUtils.isEmpty(goodsOrgansPersistence)) {
            return assignee;
        }
        Map<Long, List<GoodsOrgan>> goodsOrganMap = goodsOrgansPersistence.parallelStream()
                .collect(Collectors.groupingBy(GoodsOrgan::getOrganId));
        Set<Long> organIds = goodsOrganMap.keySet();
        List<OrganVO> want2Assign = assignee.getAssignees().stream().filter(go -> {
            return !organIds.contains(go.getId());
        }).collect(Collectors.toList());
        assignee.setAssignees(want2Assign);
        return assignee;
    }

    /**
     * 构建操作验证器
     *
     * @param goodsOrgan 商品组织的引用
     * @return OperationValidator<GoodsOrgan>
     */
    public OperationValidator<GoodsOrgan> buildDeleteOpsValidator(List<GoodsOrgan> goodsOrgan){
        OperationValidator<GoodsOrgan> deleteOpsValidator = new ReferenceValidator<>();
        deleteOpsValidator.setValidateData(goodsOrgan);
        deleteOpsValidator.setValidator(null);
        return deleteOpsValidator;
    }

    private List<GoodsOrgan> references;

    /**
     * 还有引用
     * @return true
     */
    public boolean hasReference(){
        if(this.buildDeleteOpsValidator(getReferences()).validate()){
            return true;
        }
        return false;
    }

    public List<GoodsOrgan> getReferences() {
        return references;
    }

    public void setReferences(List<GoodsOrgan> references) {
        this.references = references;
    }


}